#include "stdafx.h"
#include "STFT.h"
#include <cmath>
#include <vector>

STFT::STFT(){
}

STFT::~STFT(){
}
RingMatrix STFT::getSTFT(double* samples, double samples_length, int nfft, double sample_rate)
{
	return getSTFT(samples, samples_length, nfft, nfft, sample_rate);
}

RingMatrix STFT::getSTFT(double* samples, double samples_length, int nfft, int nhop, double SampleRate)
{
	//Spectogram
	int colums = nfft/2 + 1;
	int rows = (int)samples_length/nhop;
	RingMatrix Specgram = RingMatrix(rows, colums);

	FFT fft = FFT(nfft);
	double* window = fft.getWindow();
	 
	int wav_length = nfft;
	double* wav = new double[nfft];
	//double rms = 1;
	for(int currFrame = 0; currFrame < rows; currFrame++)
	{
		// zero pad if we run out of samples:
		int zeroPadLen = (int) (currFrame * nhop + wav_length - samples_length);
		if(zeroPadLen < 0)
			zeroPadLen = 0;
		int wavLen = wav_length - zeroPadLen;
			           
		//for(int i = 0; i<wav.length; i++)
		//    wav[i] = samples[currFrame*nhop + i];
		for(int i = 0; i < wavLen; i++)
			wav[i] = samples[currFrame * nhop + i];
		for(int i = wavLen; i < wav_length; i++)
			wav[i] = 0;
		
			       
		// window waveform
		double* re = new double[wav_length];
		double* im = new double[wav_length];
		for(int i=0; i<wav_length; i++)
		{
			re[i] = window[i] * wav[i];
			im[i] = 0;
		}
		
		// take fft
		fft.fft(re, im);
		         
		// Calculate magnitude
		for(int i=0; i<colums; i++)
		{
			if (re[i] == 0 && im[i] == 0)
				Specgram.Spectrum[currFrame][i] = 0;
			else
				Specgram.Spectrum[currFrame][i] = (double) (sqrt(re[i]*re[i] + im[i]*im[i]));//it appear at here
		}
	}  

	//Calculate Frequency

	double delta_f = (double) (SampleRate/nfft);
	Specgram.Frequency[0] = 0;
	for (int i = 1; i < colums; i++)
		Specgram.Frequency[i] = Specgram.Frequency[i - 1] + delta_f;

	//Calculate Time
	double delta_t = (double) (nfft / SampleRate);
	Specgram.Time[0] = 0;
	for (int i = 1; i < rows; i++)
		Specgram.Time[i] = Specgram.Time[i - 1] + delta_t;

 
	return Specgram;
}


//Find out in which range
int STFT::getIndex(double freq) 
{
	int i = 0;
	while(Range[i] < freq)
		i++;

	return i;
}

//Buld Range with specified the Interval
void STFT::BuildRange(double SampleRate, int Interval)
{
	Range = NULL;
	//Check
	if ((int)((SampleRate / 2)) % Interval != 0)
	{}		//throw new Exception("Range of frequency invalid. Example if Fs = 44100 then try Interval = 150");

	else
	{
		//Range
		int Range_Length = (int)(SampleRate / 2) / Interval;
		Range = new double[Range_Length];
		//Range = new double[100];
		Range[0] = Interval;
		for (int i = 1; i < Range_Length; i++)
			Range[i] = Range[i - 1] + Interval;
	}
}

////Buld Range with specified the Interval
//void STFT::BuildRange(double SampleRate, int Interval)
//{
//	Range = NULL;
//	//Check
//	if(1==0)// ((int)(SampleRate % Interval) != 0)
//	{}		//throw new Exception("Range of frequency invalid. Example if Fs = 44100 then try Interval = 150");
//
//	else
//	{
//		//Range
//		int Range_Length = (int)(SampleRate  / Interval);
//		Range = new double[Range_Length];
//		//Range = new double[100];
//		Range[0] = Interval;
//		for (int i = 1; i < Range_Length; i++)
//			Range[i] = Range[i - 1] + Interval;
//	}
//}

Dictionary STFT::getHighestSTFT(RingMatrix FullSpect, double SampleRate, int Interval)
{
	//Ranges  
	double LowerLimit;
	double UpperLimit;

	//Build Range
	BuildRange(SampleRate, Interval);
	int index = getIndex(FullSpect.Frequency[FullSpect.columns - 1]);

	std::vector<RingMatrix> HighestSpectro;


	//Data Poins Records
	int col = (int)(SampleRate/2)/Interval;
	//int col = FullSpect.columns/Interval;
	Dictionary HighestSpec = Dictionary(FullSpect.rows, col, index);
	//Dictionary<double, List<DataPoint>> dataRecord = new Dictionary<double, List<DataPoint>>();

	index = 0;
	//Time
	for (int t = 0; t < FullSpect.rows; t++)
	{
		//Set Limits
		LowerLimit = 0;
		UpperLimit = 150;

		//Highest Point by Range Initilize Magnitude equals 0
		//Create the entry with specified the Key [time]
		//dataRecord.Add(Completed.Time[i], DataPoint.HighPoints(Range.Length));

		HighestSpec.Time[t] = FullSpect.Time[t];

		//Frequency
		for (int f = 0; f < FullSpect.columns; f++)
		{
			//0 - 150 ; 150 - 300; 300 - 450...
			if (FullSpect.Frequency[f] >= LowerLimit && FullSpect.Frequency[f] <= UpperLimit)
			{
				//Find out which range we are in
				index = getIndex(FullSpect.Frequency[f]);

				//Get Max    		
				if (FullSpect.Spectrum[t][f] > HighestSpec.Spectrum[t][index])
				{
					HighestSpec.Spectrum[t][index] = FullSpect.Spectrum[t][f];
					HighestSpec.Frequency[t][index] = FullSpect.Frequency[f];
				}
			}

			else
			{
				LowerLimit = UpperLimit;
				UpperLimit = UpperLimit + 150;
				//f--;
			}
		}
	}
	return HighestSpec;
}

//Dictionary STFT::getHighestSTFT(RingMatrix FullSpect, double SampleRate, int Interval)
//{
//	//Ranges  
//	double LowerLimit;
//	double UpperLimit;
//
//	//Build Range
//	BuildRange(FullSpect.columns, Interval);
//
//	//Data Poins Records
//	//int col = (int)(SampleRate/2)/Interval;
//	int index = getIndex(FullSpect.Frequency[FullSpect.columns - 1]) + 1;
//	int col = FullSpect.columns/Interval;
//	Dictionary HighestSpec = Dictionary(FullSpect.rows, col, index);
//	//Dictionary<double, List<DataPoint>> dataRecord = new Dictionary<double, List<DataPoint>>();
//
//	index = 0;
//	//Time
//	for (int t = 0; t < FullSpect.rows; t++)
//	{
//		//Set Limits
//		LowerLimit = 0;
//		UpperLimit = 150;
//
//		//Highest Point by Range Initilize Magnitude equals 0
//		//Create the entry with specified the Key [time]
//		//dataRecord.Add(Completed.Time[i], DataPoint.HighPoints(Range.Length));
//
//		HighestSpec.Time[t] = FullSpect.Time[t];
//
//		//Frequency
//		for (int f = 0; f < FullSpect.columns; f++)
//		{
//			//0 - 150 ; 150 - 300; 300 - 450...
//			if(f == 8192 && t == 756)
//			{
//				int x;
//				x = index > 5? index : 5;
//
//			}
//			if (FullSpect.Frequency[f] >= LowerLimit && FullSpect.Frequency[f] <= UpperLimit)
//			{
//				//Find out which range we are in
//				index = getIndex(FullSpect.Frequency[f]);
//				if(f == 8192)
//				{
//					int x;
//					x = index > 5? index : 5;
//
//				}
//
//				//Get Max    		
//				if (FullSpect.Spectrum[t][f] > HighestSpec.Spectrum[t][index])
//				{
//					HighestSpec.Spectrum[t][index] = FullSpect.Spectrum[t][f];
//					HighestSpec.Frequency[t][index] = FullSpect.Frequency[f];
//				}
//			}
//
//			else
//			{
//				LowerLimit = UpperLimit;
//				UpperLimit = UpperLimit + 150;
//				//f--;
//			}
//		}
//	}
//	HighestSpec.set_frequency_columns(index + 1);
//	return HighestSpec;
//}